/*
	       File: FileProcessorSymbolTable.cs
	Create Date: 2007-09-02
	    Version:

	Description:
        Used by StringProcessor to fixup strings.  The FileProcessor Actions will use this to update the values entered.  
        For instance:
            The file copy action can use the incoming filename as its source, but the output could be set to "\\fileserver\${client}\${filename}"
            The string proc will use this class to lookup client and filename.  if those values are found they will  replace ${client} and ${filename}
        
        The search will be performed by first looking at the supplied file type, then directory, then the FileProcessor properties and finally the environment variables.
        if no value can be found an exception will be thrown.  StringProc does not handle the exception and passes it to the action to handle.  The action should log 
        the exception and then stop the workflow from proceeding.

	 Change log:
2007-09-02  JKW     CREATED

*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

using GuerillaProgrammer.Components;
using GuerillaProgrammer.FileProcessor.Settings;

namespace GuerillaProgrammer.FileProcessor
{
    public class FileProcessorSymbolTable : INameTable
    {
        #region Private member fields
        private WorkItem _CurrentWorkItem;
        private ConfigurationDirectory _ConfigurationDirectory;
        private ConfigurationFileType _ConfigurationFileType;
        private Configuration _FPConfiguration;
        #endregion

        #region Constructors and cleanup methods
        private FileProcessorSymbolTable()
        {
        }
        public FileProcessorSymbolTable(Configuration configuration, WorkItem workItem)
        {
            _FPConfiguration = configuration;
            _CurrentWorkItem = workItem;

            GetConfigurationDirectory();
            GetConfigurationFileType();
        }
        #endregion

        #region Private implementation methods
        //Constructor helpers
        private void GetConfigurationDirectory()
        {
            _ConfigurationDirectory = null;
            List<ConfigurationDirectory> directories = _FPConfiguration.Directories;
            foreach (ConfigurationDirectory directory in directories)
            {
                if (_CurrentWorkItem.DirectoryID == directory.ID)
                {
                    _ConfigurationDirectory = directory;
                    return;
                }
            }

            throw new FileProcessorSymbolTableException("Cannot find directory id " + _CurrentWorkItem.DirectoryID);
        }
        private void GetConfigurationFileType()
        {
            List<ConfigurationFileType> fileTypes = _FPConfiguration.FileTypes;
            foreach (ConfigurationFileType fileType in fileTypes)
            {
                if (_CurrentWorkItem.FileTypeID == fileType.ID)
                {
                    _ConfigurationFileType = fileType;
                    return;
                }
            }

            throw new FileProcessorSymbolTableException("Cannot find filetype id " + _CurrentWorkItem.FileTypeID);
        }

        //Symbol substitutions
        private bool SimpleSymbols(string key, ref string replacementValue)
        {
            switch (key.ToUpper())
            {
                case "GUID" :
                    replacementValue = Guid.NewGuid().ToString();
                    return true;
                case "EXT" :
                    replacementValue = Path.GetExtension(_CurrentWorkItem.OriginalName);
                    return true;
                case "FILENAME" :
                    replacementValue = Path.GetFileName(_CurrentWorkItem.OriginalName);
                    return true;
                case "FILENAMENOEXT" :
                    replacementValue = Path.GetFileNameWithoutExtension(_CurrentWorkItem.OriginalName);
                    return true;
                case "DIRECTORY" :
                    replacementValue = _ConfigurationDirectory.Path;
                    return true;
                case "FULLPATH" :
                    replacementValue = _CurrentWorkItem.Filename;
                    return true;
                case "WORKITEMFILENAME" :
                    replacementValue = _CurrentWorkItem.Filename;
                    return true;
                case "RND":
                    Random rnd = new Random((int)DateTime.Now.Ticks);
                    replacementValue = Convert.ToInt32(rnd.NextDouble() * 1000).ToString();
                    return true;
                case "ARCHIVEPATH" : 
                    replacementValue = _FPConfiguration.Services.ArchiveDirectory;
                    return true;
                default :
                    return false;
            }
        }
        private bool IsSymbol(string key, ref string replacementValue)
        {
            if (true == SimpleSymbols(key, ref replacementValue))
            {
                return true;
            }

            if ("DATE" == key.Substring(0, 4).ToUpper())
            {
                int formatStringLength = key.Length - 6;
                string formatString = key.Substring(5, formatStringLength);
                replacementValue = DateTime.Now.ToString(formatString);
                return true;
            }

            return false;
        }

        //Configuration substitution methods
        private bool GetFileTypeKey(string key, ref string replacementValue)
        {
            List<ConfigurationFileTypeParameter> parameters = _ConfigurationFileType.Parameters;
            foreach (ConfigurationFileTypeParameter parameter in parameters)
            {
                if (key == parameter.Name)
                {
                    replacementValue = parameter.Value;
                    return true;
                }
            }

            return false;
        }
        private bool GetDirectoryKey(string key, ref string replacementValue)
        {
            List<ConfigurationDirectoryParameter> parameters = _ConfigurationDirectory.Parameters;
            foreach (ConfigurationDirectoryParameter parameter in parameters)
            {
                if (key == parameter.Name)
                {
                    replacementValue = parameter.Value;
                    return true;
                }
            }

            return false;
        }
        private bool GetServicesKey(string key, ref string replacementValue)
        {
            ConfigurationServicesParameter[] parameters = _FPConfiguration.Services.Parameters;
            if (null == parameters)
            {
                return false;
            }
            foreach (ConfigurationServicesParameter parameter in parameters)
            {
                if (key == parameter.Name)
                {
                    replacementValue = parameter.Value;
                    return true;
                }
            }

            return false;
        }
        private bool GetEnvironmentKey(string key, ref string replacementValue)
        {
            string EnvironmentVariable = Environment.GetEnvironmentVariable(key);

            if (null == EnvironmentVariable)
            {
                return false;
            }

            replacementValue = EnvironmentVariable;
            return true;
        }
        #endregion

        #region Public interface
        public void Add(string key, string value)
        {
            //no reason for this
        }
        public string GetValue(string key)
        {
            string replacementValue = string.Empty;
            bool found = false;

            found = IsSymbol(key, ref replacementValue);
            if (true == found)
            {
                return replacementValue;
            }
            found = GetFileTypeKey(key, ref replacementValue);
            if (true == found)
            {
                return replacementValue;
            }
            found = GetDirectoryKey(key, ref replacementValue);
            if (true == found)
            {
                return replacementValue;
            }
            found = GetServicesKey(key, ref replacementValue);
            if (true == found)
            {
                return replacementValue;
            }
            found = GetEnvironmentKey(key, ref replacementValue);
            if (true == found)
            {
                return replacementValue;
            }

            throw new FileProcessorSymbolTableException("Could not find " + key);
        }
        #endregion
    }
}
